package cn.tedu.mall.front.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.front.service.IFrontCategoryService;
import cn.tedu.mall.pojo.front.entity.FrontCategoryEntity;
import cn.tedu.mall.pojo.front.vo.FrontCategoryTreeVO;
import cn.tedu.mall.pojo.product.vo.CategoryStandardVO;
import cn.tedu.mall.product.service.front.IForFrontCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j   //提供log对象
public class CategoryServiceImpl implements IFrontCategoryService {
    //定义一个常量作为redis的key使用
    public static final String CATEGORY_TREE_VO_KEY = "category_tree";
    //需要调用product模块从数据库中查询所有的分类信息
    @DubboReference
    private IForFrontCategoryService dubboFrontCategoryService;
    //将分类树的信息缓存到redis中，以备后续使用
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public FrontCategoryTreeVO categoryTree() {
        //1.查询redis，先判断key是否存在
        if(redisTemplate.hasKey(CATEGORY_TREE_VO_KEY)){
            //存在，直接获取缓存中的内容，返回给用户
            FrontCategoryTreeVO<FrontCategoryEntity> treeVO =
                    (FrontCategoryTreeVO<FrontCategoryEntity>) 
                            redisTemplate.boundValueOps(CATEGORY_TREE_VO_KEY).get();
            log.info("缓存中获取的分类信息");
        }
        //2.如果redis中不存在，从数据库中查询分类信息，进行三级分类树的构建
        List<CategoryStandardVO> categoryList = dubboFrontCategoryService.getCategoryList();
        //3.构建三级分类树的过程比较复杂，我们单独写在一个方法中
        FrontCategoryTreeVO<FrontCategoryEntity> treeVO = initTree(categoryList);
        //4.存储到redis中，以备后续使用
        redisTemplate.boundValueOps(CATEGORY_TREE_VO_KEY).set(treeVO);
        //记得返回
        return treeVO;
    }

    private FrontCategoryTreeVO<FrontCategoryEntity> initTree(List<CategoryStandardVO> categoryList) {
        //构建三级分类树的整个过程，分为两部分
        //第一部分：将数据库中查询到的分类信息，按父id分组存储到map中
        Map<Long,List<FrontCategoryEntity>> map = new HashMap<>();
        log.info("分类信息总大小为{}",categoryList.size());
        //遍历categoryList集合，存储到map中
        for (CategoryStandardVO categoryStandardVO : categoryList) {
            //CategoryStandardVO需要转成FrontCategoryEntity对象
            //两个对象中除了children属性不一样以外，其余都一样，所以进行同名属性赋值即可
            FrontCategoryEntity frontCategoryEntity = new FrontCategoryEntity();
            BeanUtils.copyProperties(categoryStandardVO,frontCategoryEntity);
            //获取parentId
            Long parentId = frontCategoryEntity.getParentId();
            //把parentId当作map的key使用
            //首先判断key是否存在
            if(map.containsKey(parentId)){
                //key存在了，直接将该对象赋值到value的list对象中进行存储
                map.get(parentId).add(frontCategoryEntity);
            }else{
                //key不存在，也就意味着value也不存在
                List<FrontCategoryEntity> value = new ArrayList<>();
                value.add(frontCategoryEntity);
                map.put(parentId,value);
            }
        }
        //第二部分：构建三级分类树
        //从map中获取到对应的parentId获取到value中的分类信息
        //获取一级分类信息，parentId为0
        List<FrontCategoryEntity> firstLevels = map.get(0L);
        //判断firstLevels是否为null，如果为空，直接终止程序运行
        if(firstLevels==null)
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"项目必须要有根分类");
        //遍历一级分类信息
        for (FrontCategoryEntity firstLevel : firstLevels) {
            //获取一级分类信息的id，是二级分类的父id
            Long secondLevelParentId = firstLevel.getId();
            //根据二级分类的父id获取二级分类的信息
            List<FrontCategoryEntity> secondLevels = map.get(secondLevelParentId);
            //判断secondLevels是否为空，如果为空，跳出本次循环，进入下一次循环
            if(secondLevels==null){
                log.info("当前一级分类{}，没有二级分类信息",firstLevel);
                continue;
            }
            //遍历二级分类信息
            for (FrontCategoryEntity secondLevel : secondLevels) {
                //获取二级分类信息的id，是三级分类的父id
                Long thirdLevelParentId = secondLevel.getId();
                //获取三级分类信息
                List<FrontCategoryEntity> thirdLevels = map.get(thirdLevelParentId);
                //判断thirdLevels是否为null，如果为空，跳出本次循环，进入下一次循环
                if(thirdLevels==null){
                    log.info("当前二级分类{}，没有三级分类信息",secondLevel);
                    continue;
                }
                //课程中设计，只有三级分类，所以三级分类信息对象不需要再遍历
                //需要将三级分类对象，赋值到二级分类对象中的childrens属性中
                secondLevel.setChildrens(thirdLevels);
            }
            //将二级分类对象，赋值到一级分类对象的childrens属性中
            firstLevel.setChildrens(secondLevels);
        }
        //本方法返回指类型FrontCategoryTreeVO<FrontCategoryEntity>
        FrontCategoryTreeVO<FrontCategoryEntity> treeVO = new FrontCategoryTreeVO<>();
        //将一级分类信息对象赋值到treeVO中
        treeVO.setCategories(firstLevels);
        return treeVO;
    }
}
